Move marketplace definitions to openhands.sdk.marketplace module#2786
Move marketplace definitions to openhands.sdk.marketplace module#2786
Conversation
Create a new openhands.sdk.marketplace module to house marketplace-related types (Marketplace, MarketplaceEntry, MarketplaceOwner, etc.) that were previously embedded in openhands.sdk.plugin.types. Changes: - Add openhands-sdk/openhands/sdk/marketplace/ module with types.py - Update plugin/types.py with deprecation-tracking __getattr__ re-exports - Update plugin/__init__.py with lazy imports and deprecation warnings - Update internal references in skills modules to use new location - Add tests/sdk/marketplace/test_deprecation.py for deprecation tracking The old import paths (openhands.sdk.plugin.Marketplace, etc.) still work but emit DeprecatedWarning. Users should migrate to importing from openhands.sdk.marketplace instead. Deprecation timeline: - deprecated_in: 1.16.0 - removed_in: 1.19.0 Co-authored-by: openhands <openhands@all-hands.dev>
Python API breakage checks — ✅ PASSEDResult: ✅ PASSED |
REST API breakage checks (OpenAPI) — ✅ PASSEDResult: ✅ PASSED |
Restructure tests to match the new module structure: - Move tests/sdk/plugin/test_marketplace.py -> tests/sdk/marketplace/test_marketplace.py - Update imports to use openhands.sdk.marketplace (canonical location) Co-authored-by: openhands <openhands@all-hands.dev>
Coverage Report •
|
||||||||||||||||||||||||||||||||||||||||||||||||||
all-hands-bot
left a comment
There was a problem hiding this comment.
🟢 Good taste - Clean refactoring
Verdict: ✅ Merge it
Key insight: The different __getattr__ patterns (eager import in __init__.py, lazy in types.py) are intentional to avoid circular dependencies since marketplace.types imports from plugin.types. Good design.
Proper deprecation timeline (1.16→1.19), backward compatibility maintained, well-tested. No agent behavior changes, no eval impact.
all-hands-bot
left a comment
There was a problem hiding this comment.
QA Report: Marketplace Module Refactor
✅ PASS
Summary: The refactor successfully moves marketplace definitions to a new module with full backward compatibility and proper deprecation warnings.
Environment Setup
✅ Build successful
$ make build
Dependencies installed successfully.
Pre-commit hooks installed successfully.
Build complete! Development environment is ready.CI & Test Status
✅ All critical CI checks passed:
- ✅ sdk-tests (2m14s)
- ✅ cross-tests (1m20s)
- ✅ Python API breakage checks (23s)
- ✅ REST API checks (32s)
- ✅ pre-commit (1m14s)
- ✅ agent-server-tests, tools-tests
✅ Local test results:
$ uv run pytest tests/sdk/marketplace/ -v
50 passed in 0.13s
- 11 deprecation tests (new)
- 39 marketplace functionality tests (moved from plugin/)Functional Verification
1. Import Behavior ✅
Tested both new and old import paths to verify backward compatibility:
New import path (no warnings):
from openhands.sdk.marketplace import Marketplace, MarketplaceOwner, ...
✓ Imports successful with 0 warningsOld import paths (deprecation warnings):
from openhands.sdk.plugin import Marketplace
✓ Imports successful with proper DeprecatedWarning:
"Importing Marketplace from openhands.sdk.plugin is deprecated
as of 1.16.0 and will be removed in 1.19.0. Import from
openhands.sdk.marketplace instead."Class identity verification:
Marketplace is OldMarketplace: True
MarketplaceOwner is OldMarketplaceOwner: True
✓ Both import paths return identical classes2. Marketplace Functionality ✅
Verified all marketplace classes instantiate and function correctly:
# All classes work with new import location
owner = MarketplaceOwner(name="Test Team", email="test@example.com")
entry = MarketplaceEntry(name="test-skill", source="./skills/test")
plugin_entry = MarketplacePluginEntry(name="test-plugin", ...)
source = MarketplacePluginSource(source="github", repo="owner/repo")
metadata = MarketplaceMetadata(version="1.0.0")
✓ All classes instantiate correctly3. Marketplace.load() Method ✅
Tested loading a real marketplace:
$ uv run python -c "from openhands.sdk.marketplace import Marketplace; ..."
Marketplace loaded successfully!
Name: mixed-skills-marketplace
Owner: OpenHands Team
Skills: 2 skill(s)
Plugins: 0 plugin(s)
✓ Marketplace loading works correctly4. Example Integration ✅
Verified the updated example runs without errors:
$ cd examples/01_standalone_sdk/43_mixed_marketplace_skills
$ uv run python main.py --list
Installed Skills
No skills installed.
EXAMPLE_COST: 0
✓ Example runs successfully with new import path5. Skills Module Integration ✅
Verified internal SDK code that uses marketplace works:
$ uv run pytest tests/sdk/skills/test_installed_skills.py -k marketplace -v
5 passed
- test_install_local_skills
- test_install_skills_force_overwrite
- test_install_handles_missing_skill_source
- test_install_skills_from_plugin_directories
- test_install_both_standalone_and_plugin_skills
✓ Skills integration with marketplace works correctlyVerification Summary
✅ All changed behavior verified:
- New module
openhands.sdk.marketplacecontains all marketplace types - Old import paths continue to work with deprecation warnings
- Deprecation warnings properly reference version 1.16.0 (deprecated) and 1.19.0 (removal)
- All marketplace functionality preserved
- Example code updated and functional
- Internal SDK code updated and functional
- No breaking changes to public API
- All tests pass (50 marketplace tests + 212 plugin tests + 5 skills integration tests)
Migration Path Verification ✅
The PR provides a clear migration path:
Before (deprecated but still works):
from openhands.sdk.plugin import MarketplaceAfter (recommended):
from openhands.sdk.marketplace import MarketplaceUsers have 3 minor versions (1.16.0 → 1.19.0) to migrate.
Verdict
✅ PASS - This is a clean refactor that:
- Improves code organization by separating marketplace from plugin concerns
- Maintains full backward compatibility with deprecation warnings
- Provides a clear migration path with 3-version runway
- Preserves all functionality
- Updates all internal references
- Includes comprehensive test coverage
No issues found. Ready for merge.
enyst
left a comment
There was a problem hiding this comment.
I think it's nice that we use them for skills, I don't know what the plugin format will become, it feels a bit... fluid. But skills are so important and widespread that it's nice to use/reuse a bucket of them IMHO.
Why
The marketplace definitions (Marketplace, MarketplaceEntry, MarketplaceOwner, etc.) were embedded in the plugin module but represent a distinct domain. Moving them to their own module improves code organization and makes the SDK structure clearer.
The official Anthropic spec has marketplaces for plugins only. But we use them to point to skills, so if nothing else we should move them out of the
openhands.sdk.pluginmodule.Summary
openhands.sdk.marketplacemodule to house marketplace-related typesopenhands.sdk.pluginwith deprecation-tracking re-exports for backward compatibilityIssue Number
N/A (refactoring for better code organization)
How to Test
The changes can be verified by running:
Test Results:
Import Behavior:
Video/Screenshots
N/A (internal refactoring, no UI changes)
Type
Notes
Deprecation Timeline:
deprecated_in: 1.16.0removed_in: 1.19.0Migration Guide:
All marketplace classes are affected:
MarketplaceMarketplaceEntryMarketplaceOwnerMarketplacePluginEntryMarketplacePluginSourceMarketplaceMetadataMARKETPLACE_MANIFEST_DIRSMARKETPLACE_MANIFEST_FILE@csmith49 can click here to continue refining the PR
Agent Server images for this PR
• GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server
Variants & Base Images
eclipse-temurin:17-jdknikolaik/python-nodejs:python3.13-nodejs22-slimgolang:1.21-bookwormPull (multi-arch manifest)
# Each variant is a multi-arch manifest supporting both amd64 and arm64 docker pull ghcr.io/openhands/agent-server:f4dffd3-pythonRun
All tags pushed for this build
About Multi-Architecture Support
f4dffd3-python) is a multi-arch manifest supporting both amd64 and arm64f4dffd3-python-amd64) are also available if needed